/******************************************************************************
MSP430F2272 Project Creator 4.0

ME 461 - S. R. Platt
Fall 2010

Updated for CCSv4.2 Rick Rekoske 8/10/2011

Written by: Steve Keres
College of Engineering Control Systems Lab
University of Illinois at Urbana-Champaign
*******************************************************************************/

#include "msp430g2553.h"

#define	SET_BIT8(reg, bit)		( reg |=  (0x01   << bit) )
#define	CLEAR_BIT8(reg, bit)	( reg &= ~(0x01   << bit) )
#define	SET_BIT16(reg, bit)		( reg |=  (0x0001 << bit) )
#define	CLEAR_BIT16(reg, bit)	( reg &= ~(0x0001 << bit) )

#define	I2C_OWN_ADDR	0x20		// address 0x40 -> we receive from master, 0x41 -> we write byte to I2C bus


unsigned int	inc = 1;		// debugging incremental counter

unsigned char	i2cdata = 0x0;	// scratch pad for playing with i2c info

char newprint = 0;
unsigned long timecnt = 0;

void main(void) {
	
	// stop the watchdog timer
	WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
	
	// set up internal clocking
	if (CALBC1_16MHZ ==0xFF || CALDCO_16MHZ == 0xFF) while(1);	// set up to use internal oscillator                                             
	DCOCTL = CALDCO_16MHZ;                		// Set uC to run at approximately 16 Mhz
	BCSCTL1 = CALBC1_16MHZ; 
	
	// set up status "I'm alive!" LED
	P1DIR |= 0x1;								// Default LED output - P1.0
	
	// Timer A0 Config - periodic interrupts
	TA0CCTL0 = CCIE;                           // Enable interrupt
	TA0CCR0 = 1600;                           // period = .1ms   
	TA0CTL = TASSEL_2 + MC_1;                  // source SMCLK, up mode

	// Timer A1 config - PWM
	
	
	// USCI_B config, I2C Slave
	// set CTL1 first, to keep in reset while configuring everything else
	UCB0CTL1 = 	UCTR * 0 + 			// set as receiver
				UCSWRST;			// keep in reset
				
	UCB0CTL0 = 	UCA10 * 0 +			// 0 = use 7-bit addresses for own address
				UCMST * 0 +			// 0 = we are I2C slave
				UCMODE_3 +			// I2C mode
				UCSYNC * 1;			// synchronous operation

	UCB0I2COA = (UCGCEN * 0) + I2C_OWN_ADDR;		// UCGEN = 0 -> do not respond to general call
				
	SET_BIT8(P1SEL, 7);  // on g2553, UCB0SDA -> P1.7, bit 7 of P1SEL, P3SEL.7 = 1
	SET_BIT8(P1SEL, 6);  // on g2553, UCB0SCL -> P1.6, bit 6 of P1SEL, P3SEL.6 = 1

	UCB0CTL1 &= ~UCSWRST;	// take out of reset (after configuring everything but before enabling interrupts)
	
	IE2 |= UCB0TXIE | UCB0RXIE;		// enable interrupts on TX and RX
		

  _BIS_SR(GIE); 						    						// Enable global interrupt

	
  while(1) {  
  	
    if (newprint)  { 
    	P1OUT ^= 0x1;		// Blink LED
     
      newprint = 0;
    }
    
  }
}


// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{

  timecnt++; // Keep track of time for main while loop. 

  if ((timecnt%5000) == 0) {  // 1/2 second
    newprint = 1;  // flag main while loop that .5 seconds have gone by.  
  }
      
}

// I2C TX interrupt - bus master is asking for a byte from us
#pragma vector=USCIAB0TX_VECTOR
__interrupt void I2C_TX(void)
{
	if(IFG2&UCB0TXIFG) {  // USCI_B0 requested TX interrupt (need to write a byte to UCB0TXBUF)
		UCB0TXBUF = i2cdata * 3;	// write out 3x the value in i2cdata
		IFG2 &= ~UCB0TXIFG;   // clear IFG
	}
}

// I2C RX interrupt - bus master has written a byte to us and we need to do something
#pragma vector=USCIAB0RX_VECTOR
__interrupt void I2C_RX(void)
{
	if(IFG2&UCB0RXIFG) {  // USCI_B0 requested RX interrupt (need to read a byte from UCB0RXBUF)
		i2cdata = UCB0RXBUF;	
		IFG2 &= ~UCB0RXIFG;   // clear IFG
	}
}




